#pragma once
#include"const.h"
// 辅助函数，将单个参数转换为字符串
template<typename T>
std::string to_string_helper(T&& arg) {
    std::ostringstream oss;
    oss << std::forward<T>(arg);
    return oss.str();
}
// 线程安全的日志队列
class LogQueue {
public:
    void push(const std::string& msg) {
        std::lock_guard<std::mutex> lock(mutex_);
        queue_.push(msg);
        cond_var_.notify_one();
    }

    bool pop(std::string& msg) {
        std::unique_lock<std::mutex> lock(mutex_);
        while (queue_.empty() && !is_shutdown_) {
            cond_var_.wait(lock);
        }
        if (is_shutdown_ && queue_.empty()) {
            return false;
        }
        msg = queue_.front();
        queue_.pop();
        return true;
    }

    void shutdown() {
        std::lock_guard<std::mutex> lock(mutex_);
        is_shutdown_ = true;
        cond_var_.notify_all();
    }

private:
    std::queue<std::string> queue_;
    std::mutex mutex_;
    std::condition_variable cond_var_;
    bool is_shutdown_ = false;
};
enum class LogLevel {
    INFO, DEBUG, WARN, ERROR
};
class Logger
{
public:
    Logger(const std::string& filename, bool console_output = false) : log_file_(filename, std::ios::out | std::ios::app),
        exit_flag_(false), console_output_(console_output) {
        if (!log_file_.is_open()) {
            throw std::runtime_error("无法打开日志文件");
        }
        worker_thread_ = std::thread(&Logger::processQueue, this);
    }

    ~Logger();
    // 日志接口：支持带格式字符串的日志
    template<typename... Args>
    void log(LogLevel level, const std::string& format, Args&&... args) {
        std::string level_str;
        switch (level) {
        case LogLevel::INFO:
            level_str = "[INFO] ";
            break;
        case LogLevel::DEBUG:
            level_str = "[DEBUG] ";
            break;
        case LogLevel::WARN:
            level_str = "[WARN] ";
            break;
        case LogLevel::ERROR:
            level_str = "[ERROR] ";
            break;
        }
        log_queue_.push(level_str + formatMessage(format, std::forward<Args>(args)...));
    }
private:
    std::string getCurrentTime();

    LogQueue log_queue_;
    std::thread worker_thread_;
    std::ofstream log_file_;
    std::atomic<bool> exit_flag_;
    bool console_output_; // 控制是否输出到控制台
    void processQueue();
    // 使用模板折叠格式化日志消息，支持 "{}" 占位符
    template<typename... Args>
    std::string formatMessage(const std::string& format, Args&&... args) {
        std::vector<std::string> arg_strings = { to_string_helper(std::forward<Args>(args))... };
        std::ostringstream oss;
        size_t arg_index = 0;
        size_t pos = 0;
        size_t placeholder = format.find("{}", pos);
        while (placeholder != std::string::npos) {
            oss << format.substr(pos, placeholder - pos);
            if (arg_index < arg_strings.size()) {
                oss << arg_strings[arg_index++];
            }
            else {
                // 没有足够的参数，保留 "{}"
                oss << "{}";
            }
            pos = placeholder + 2; // 跳过 "{}"
            placeholder = format.find("{}", pos);
        }
        // 添加剩余的字符串
        oss << format.substr(pos);
        // 如果还有剩余的参数，按原方式拼接
        while (arg_index < arg_strings.size()) {
            oss << arg_strings[arg_index++];
        }
        return" [" + getCurrentTime() + "]" + oss.str();
    }
};


